#include "drawer.h"
#include <iostream>
using namespace std;
//! Constructor
Drawer::Drawer() {
}

//! The method draws the Object of type Parallelepiped
void Drawer::draw(Parallelepiped para, double r, double g, double b){
	glMatrixMode(GL_MODELVIEW);
	//glLoadIdentity();

/* Colocar Normais*/

	glPushMatrix();
		glTranslated( para.getPosition().x, para.getPosition().y, para.getPosition().z);
		
		glRotated( para.getAzimuthX()/DegreesToRadians, 1., 0., 0.);
		glRotated( para.getAzimuthY()/DegreesToRadians, 0., 1., 0.);
		glRotated( para.getAzimuthZ()/DegreesToRadians, 0., 0., 1.);
		
		glScaled(para.getWidth(), para.getHeight(), para.getDepth());		

		glColor3d(r, g, b);
		//Top, Bottom, Front and Back Sides
		/*glBegin( GL_QUAD_STRIP );
			glNormal3f(-para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( -para.getWidth()/2., -para.getHeight()/2, para.getDepth()/2 );
			
			glNormal3f(para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( para.getWidth()/2., -para.getHeight()/2., para.getDepth()/2. );

			glNormal3f(-para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( -para.getWidth()/2, para.getHeight()/2, para.getDepth()/2 );

			glNormal3f(para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( para.getWidth()/2, para.getHeight()/2, para.getDepth()/2 );

			glNormal3f(-para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( -para.getWidth()/2, para.getHeight()/2, -para.getDepth()/2 );

			glNormal3f(para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( para.getWidth()/2, para.getHeight()/2, -para.getDepth()/2 );

			glNormal3f(-para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( -para.getWidth()/2, -para.getHeight()/2, -para.getDepth()/2 );

			glNormal3f(para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( para.getWidth()/2, -para.getHeight()/2, -para.getDepth()/2 );

			glNormal3f(-para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( -para.getWidth()/2., -para.getHeight()/2, para.getDepth()/2 );

			glNormal3f(para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( para.getWidth()/2., -para.getHeight()/2., para.getDepth()/2. );
		glEnd();

		//Right Side
		glBegin( GL_QUAD_STRIP );
			glNormal3f(para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( para.getWidth()/2, -para.getHeight()/2, para.getDepth()/2 );

			glNormal3f(para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( para.getWidth()/2, -para.getHeight()/2, -para.getDepth()/2 );

			glNormal3f(para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( para.getWidth()/2, para.getHeight()/2, para.getDepth()/2 );

			glNormal3f(para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( para.getWidth()/2, para.getHeight()/2, -para.getDepth()/2 );
		glEnd();

		//Front Side
		glBegin( GL_QUAD_STRIP );
			glNormal3f(-para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( -para.getWidth()/2, -para.getHeight()/2, -para.getDepth()/2 );

			glNormal3f(-para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( -para.getWidth()/2, -para.getHeight()/2, para.getDepth()/2 );

			glNormal3f(-para.getWidth()/2., 0, para.getDepth()/2);
			glVertex3d( -para.getWidth()/2, para.getHeight()/2, -para.getDepth()/2 );

			glNormal3f(-para.getWidth()/2., 0, -para.getDepth()/2);
			glVertex3d( -para.getWidth()/2, para.getHeight()/2, para.getDepth()/2 );
		glEnd();*/

		glutSolidCube(1);

	glPopMatrix();
}

//! The method draws the Object of type Sphere
void Drawer::draw(Sphere sphere, double r, double g, double b){
	// x,y,z in [0,1]
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
			glTranslated(sphere.getPosition().x, sphere.getPosition().y, sphere.getPosition().z);
			glColor3f(r, g, b);
			glutSolidSphere(sphere.getRadius(),NUMSEGS,NUMSEGS);
		glPopMatrix();

}

//! The method draws the Object of type Pyramid
void Drawer::draw(Pyramid pyramid, double r, double g, double b){
	glMatrixMode(GL_MODELVIEW);
	//glLoadIdentity();

	glPushMatrix();
		glTranslated( pyramid.getPosition().x, pyramid.getPosition().y, pyramid.getPosition().z);
		
		glRotated( pyramid.getAzimuthX()/DegreesToRadians, 1., 0., 0.);
		glRotated( pyramid.getAzimuthY()/DegreesToRadians, 0., 1., 0.);
		glRotated( pyramid.getAzimuthZ()/DegreesToRadians, 0., 0., 1.);

		glColor3d(r, g, b);
		//Bottom
		glBegin( GL_QUAD_STRIP );
			glNormal3d( 0., -1., 0. );
			glVertex3d( -pyramid.getWidth()/2, -pyramid.getHeight()/2, -pyramid.getDepth()/2 );
			glVertex3d( pyramid.getWidth()/2, -pyramid.getHeight()/2, -pyramid.getDepth()/2 );
			glVertex3d( -pyramid.getWidth()/2, -pyramid.getHeight()/2, pyramid.getDepth()/2 );
			glVertex3d( pyramid.getWidth()/2, -pyramid.getHeight()/2, pyramid.getDepth()/2 );
		glEnd();

		//Lateral Faces
		vec3 vtop, v1, v2, v3, v4, c1, c2, c3, c4;
		vtop = vec3( 0., pyramid.getHeight()/2, 0. );
		v1 = vec3( -pyramid.getWidth()/2, -pyramid.getHeight()/2, -pyramid.getDepth()/2 );
		v2 = vec3( -pyramid.getWidth()/2, -pyramid.getHeight()/2, pyramid.getDepth()/2 );
		v3 = vec3( pyramid.getWidth()/2, -pyramid.getHeight()/2, pyramid.getDepth()/2 );
		v4 = vec3( pyramid.getWidth()/2, -pyramid.getHeight()/2, -pyramid.getDepth()/2 );

		c1 = cross( v1 - vtop, v2 - vtop);
		c2 = cross( v2 - vtop, v3 - vtop);
		c3 = cross( v3 - vtop, v4 - vtop);
		c4 = cross( v4 - vtop, v1 - vtop);

		glBegin( GL_POLYGON );
			glNormal3f( c1.x, c1.y, c1.z );
			glVertex3f( vtop.x, vtop.y, vtop.z );
			glVertex3f( v1.x, v1.y, v1.z );
			glVertex3f( v2.x, v2.y, v2.z );
		glEnd();
		glBegin( GL_POLYGON );
			glNormal3f( c2.x, c2.y, c2.z );
			glVertex3f( vtop.x, vtop.y, vtop.z );
			glVertex3f( v2.x, v2.y, v2.z );
			glVertex3f( v3.x, v3.y, v3.z );
		glEnd();
		glBegin( GL_POLYGON );
			glNormal3f( c3.x, c3.y, c3.z );
			glVertex3f( vtop.x, vtop.y, vtop.z );
			glVertex3f( v3.x, v3.y, v3.z );
			glVertex3f( v4.x, v4.y, v4.z );
		glEnd();
		glBegin( GL_POLYGON );
			glNormal3f( c4.x, c4.y, c4.z );
			glVertex3f( vtop.x, vtop.y, vtop.z );
			glVertex3f( v4.x, v4.y, v4.z );
			glVertex3f( v1.x, v1.y, v1.z );
		glEnd();
	glPopMatrix();

}

void Drawer::draw(Tetrahedron tetra, double r, double g, double b){
	glMatrixMode(GL_MODELVIEW);
	//glLoadIdentity();

	glPushMatrix();
		glTranslated( tetra.getPosition().x, tetra.getPosition().y, tetra.getPosition().z);
		
		glRotated( tetra.getAzimuthX()/DegreesToRadians, 1., 0., 0.);
		glRotated( tetra.getAzimuthY()/DegreesToRadians, 0., 1., 0.);
		glRotated( tetra.getAzimuthZ()/DegreesToRadians, 0., 0., 1.);

		glColor3d(r, g, b);

		// Lateral Faces
		vec3 vtop, v1, v2, v3, c1, c2, c3;
		vtop = vec3( 0., 2*tetra.getHeight()/3, 0. );

		v1 = vec3( -tetra.getWidth()/2, -tetra.getHeight()/3, tetra.getDepth()/3 );
		v2 = vec3( tetra.getWidth()/2, -tetra.getHeight()/3, tetra.getDepth()/3 );
		v3 = vec3( 0., -tetra.getHeight()/3, -2*tetra.getDepth()/3 );

/*		v1 = vec3( -tetra.getWidth()/2, -tetra.getHeight()/2, tetra.getDepth()/2 );
		v2 = vec3( tetra.getWidth()/2, -tetra.getHeight()/2, tetra.getDepth()/2 );
		v3 = vec3( 0., -tetra.getHeight()/2, -tetra.getDepth()/2 );
*/
		c1 = cross( v1 - vtop, v2 - vtop);
		c2 = cross( v2 - vtop, v3 - vtop);
		c3 = cross( v3 - vtop, v1 - vtop);

		glBegin( GL_POLYGON );
			glNormal3d( c1.x, c1.y, c1.z );
			glVertex3d( vtop.x, vtop.y, vtop.z );
			glVertex3d( v1.x, v1.y, v1.z );
			glVertex3d( v2.x, v2.y, v2.z );
		glEnd();
		glBegin( GL_POLYGON );
			glNormal3d( c2.x, c2.y, c2.z );
			glVertex3d( vtop.x, vtop.y, vtop.z );
			glVertex3d( v2.x, v2.y, v2.z );
			glVertex3d( v3.x, v3.y, v3.z );
		glEnd();
		glBegin( GL_POLYGON );
			glNormal3d( c3.x, c3.y, c3.z );
			glVertex3d( vtop.x, vtop.y, vtop.z );
			glVertex3d( v3.x, v3.y, v3.z );
			glVertex3d( v1.x, v1.y, v1.z );
		glEnd();

		// Base
		glBegin( GL_TRIANGLE_FAN );
			glNormal3d( 0., -1., 0. );
			glVertex3d( v1.x, v1.y, v1.z );
			glVertex3d( v3.x, v3.y, v3.z );
			glVertex3d( v2.x, v2.y, v2.z );
		glEnd();
	glPopMatrix();
}

//! The method draws the Object of type Cylinder
void Drawer::draw(Cylinder cyl, double r, double g, double b){
	glMatrixMode(GL_MODELVIEW);
	//glLoadIdentity();

	glPushMatrix();
		glColor3d(r, g, b);

		glTranslated( cyl.getPosition().x, cyl.getPosition().y, cyl.getPosition().z);
		
		glRotated( cyl.getAzimuthX()/DegreesToRadians, 1., 0., 0.);
		glRotated( cyl.getAzimuthY()/DegreesToRadians, 0., 1., 0.);
		glRotated( cyl.getAzimuthZ()/DegreesToRadians, 0., 0., 1.);
		
		// Translate and Rotate to vertical position
		glTranslated( 0., cyl.getHeight()/2 , 0. );
		glRotated( 90., 1., 0., 0. );

		glScaled( cyl.getWidth(), cyl.getHeight(), cyl.getDepth() );

		glutSolidCylinder(.5,1.,16,16);

	glPopMatrix();
}

//! The method draws the Object of type Cone
void Drawer::draw(Cone cone, double r, double g, double b){
	glMatrixMode(GL_MODELVIEW);
	//glLoadIdentity();

	glPushMatrix();
		glColor3d(r, g, b);
		glTranslated( cone.getPosition().x, cone.getPosition().y, cone.getPosition().z);
		
		glRotated( cone.getAzimuthX()/DegreesToRadians, 1., 0., 0.);
		glRotated( cone.getAzimuthY()/DegreesToRadians, 0., 1., 0.);
		glRotated( cone.getAzimuthZ()/DegreesToRadians, 0., 0., 1.);
		
		// Translate and Rotate to vertical position
		glTranslated( 0., -cone.getHeight()/2 , 0. );
		glRotated( 270., 1., 0., 0. );

		glScaled( cone.getWidth(), cone.getHeight(), cone.getDepth() );

		glutSolidCone(.5,1.,16,16);

	glPopMatrix();
}
